import { Injectable } from "@nestjs/common";
import { InjectRepository } from "@nestjs/typeorm";
import { OrgClosure, OrgEntity } from "./entity/org.entity";
import { In, Like, Repository } from "typeorm";
import { AddOrgDto } from "./dto/addOrgDto";
import { orgPageDto } from "./dto/pageOrgDto";
import { PageMap } from 'src/store/vo/BodyDto'
import { EditOrg } from "./dto/editOrgDto";
import { UpdateOrg } from "./dto/deleteOrgDto";
import { formatTime } from "src/utils/disposeTime";

@Injectable()
export class OrgRepository {

  constructor(
    @InjectRepository(OrgEntity) private readonly orgRepository: Repository<OrgEntity>,
    @InjectRepository(OrgClosure) private readonly orgClosureRepository: Repository<OrgClosure>
  ) { }

  /**
   * 查询指定组织及所有下级组织
   * @param orgId 组织Id
   * @returns 扁平数组
   */
  async getOrgTree(orgId: number | null = null) {
    return (await this.orgRepository.query(`
      WITH RECURSIVE descendants AS (
	      SELECT d.id,d.org_name,e.ancestor_id from test_org d LEFT JOIN test_org_closure e on d.id = e.descendant_id where d.id = $1
	      UNION ALL
	      select a.id,a.org_name,b.ancestor_id from test_org a INNER JOIN test_org_closure b ON a.id = b.descendant_id INNER JOIN descendants c on c.id = b.ancestor_id
	    ) SELECT id,org_name,ancestor_id FROM descendants
      `, [orgId])).map((item: any) => {
      return {
        id: item.id,
        value: item.id,
        label: item.org_name,
        parentId: item.ancestor_id
      }
    })
  }

  /**
   * 新增组织架构
   * @param dto 参数
   * @returns true or false
   */
  async addOrg(dto: AddOrgDto): Promise<boolean> {
    // save 方法有责更新，无责插入
    return await new Promise((resolve) => {
      this.orgRepository.manager.transaction(async () => {
        const result = await this.orgRepository.save(dto)
        const result2 = await this.orgClosureRepository.save({ descendantId: result.id, ancestorId: dto.parentId })

        if (result?.id && result2?.id) {
          resolve(true)
        } else {
          resolve(false)
        }
      }).catch(() => {
        resolve(false)
      })
    })
  }

  /**
   * 查询组织架构分页
   * @param params 参数
   * @returns 列表数据和总数
   */
  async orgPage(params: orgPageDto): Promise<PageMap> {

    const conditions: any = {
      delete_flag: false,
      createUserId: In(params.premissionIds)
    }

    if (params?.name) {
      conditions.orgName = Like(`%${params.name}%`)
    }

    const [data, total] = await this.orgRepository.findAndCount({
      where: conditions,
      skip: params.start,
      take: params.limit,
      order: {
        id: 'DESC'
      }
    })

    return { rows: formatTime(data, ['createTime']), total }
  }

  /**
   * 查询组织架构详情
   * @param params 参数
   * @returns 详情
   */
  async getDetail(params: { id: number }): Promise<OrgEntity | null> {
    return (await this.orgRepository.query(`
        select org.id,org.org_name,b.ancestor_id from test_org org
        left join test_org_closure b on org.id = b.descendant_id
        where org.id = $1 and org.delete_flag = false
      `, [params.id])).map((item: any) => {
      return {
        id: item.id,
        orgName: item.org_name,
        parentId: item.ancestor_id,
      }
    })?.[0]
  }

  /**
   * 修改组织架构
   * @param dto 参数
   * @returns true or false
   */
  async editOrg(dto: EditOrg): Promise<boolean> {
    return await new Promise((resolve) => {
      this.orgRepository.manager.transaction(async () => {
        const result = await this.orgClosureRepository.createQueryBuilder()
          .update()
          .set({ ancestorId: dto.parentId })
          .where("descendantId = :descendantId", { descendantId: dto.id })
          .execute()
        const result2 = await this.orgRepository.createQueryBuilder()
          .update()
          .set({ orgName: dto.orgName })
          .where("id = :id", { id: dto.id })
          .execute()

        if (result?.affected && result2?.affected) {
          resolve(true)
        } else {
          resolve(false)
        }
      }).catch(() => {
        resolve(false)
      })
    })
  }

  /**
   * 删除组织架构
   * @param params 参数
   * @returns true or false
   */
  async deleteOrg(params: UpdateOrg): Promise<boolean> {
    const result = await this.orgRepository.createQueryBuilder()
      .update(OrgEntity)
      .set({
        updateUserId: params.updateUserId,
        delete_flag: true
      })
      .where("id = :id", { id: params.id })
      .execute()

    return (result?.affected ?? 0) > 0
  }
}